// 导入必要的模块
import * as step from '@flow-step/step-toolkit';
import * as authUtil from '../src/auth-helper';
import { IGitSourceParams } from '../src/git-source-params';
import { updateGitConfigSettings } from '../src/git-config-settings';
import { GitOutput } from '../src/git-command-helper';
import * as sinon from 'sinon';
import { expect } from 'chai';

// 使用 Mocha 描述测试套件
describe('updateGitConfigSettings', () => {
    let sandbox: sinon.SinonSandbox;
    let getHostStub: sinon.SinonStub;
    let updateConfigFnStub: sinon.SinonStub;
    let stepInfoStub: sinon.SinonStub;

    // 在每个测试之前初始化 Sinon 沙箱和存根
    beforeEach(() => {
        sandbox = sinon.createSandbox();
        getHostStub = sandbox.stub(authUtil, 'getHost');
        updateConfigFnStub = sandbox.stub().resolves({} as GitOutput);
        stepInfoStub = sandbox.stub(step, 'info');
        
        // 清理环境变量
        delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN;
        delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP;
    });

    // 在每个测试之后恢复 Sinon 沙箱
    afterEach(() => {
        sandbox.restore();
    });

    // 测试 Git 主机名为空的情况
    it('should return early if gitHost is undefined', async () => {
        getHostStub.returns(undefined);
        await updateGitConfigSettings('action', { gitRepo: '', workDir: '' } as IGitSourceParams, false, updateConfigFnStub);
        expect(updateConfigFnStub.callCount).to.equal(0);
    });

    describe('参数组合测试', () => {
        describe('组合1: action="add" + useInnerApiHost=true', () => {
            it('should set inner host redirect config when conditions are met', async () => {
                getHostStub.returns('codeup.aliyun.com');
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN = 'internal.codeup.aliyun.com';
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP = '192.168.1.1';
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('add', input, true, updateConfigFnStub);

                // 验证内网域名被设置
                expect(stepInfoStub.calledWith('gitInnerHost = internal.codeup.aliyun.com')).to.be.true;
                
                // 验证配置函数被调用6次（HTTP协议，使用内网域名）
                expect(updateConfigFnStub.callCount).to.equal(6);
                
                // 验证内网域名重定向配置
                expect(updateConfigFnStub.firstCall.args[2]).to.include('url.https://user:password@internal.codeup.aliyun.com.insteadOf');
                expect(updateConfigFnStub.firstCall.args[3]).to.include('http://user:password@codeup.aliyun.com');
                
                expect(updateConfigFnStub.secondCall.args[2]).to.include('url.https://user:password@internal.codeup.aliyun.com.insteadOf');
                expect(updateConfigFnStub.secondCall.args[3]).to.include('https://user:password@codeup.aliyun.com');
            });

            it('should set inner host redirect config for SSH URLs', async () => {
                getHostStub.returns('codeup.aliyun.com');
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN = 'internal.codeup.aliyun.com';
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP = '192.168.1.1';
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    sshUrl: true
                } as IGitSourceParams;

                await updateGitConfigSettings('add', input, true, updateConfigFnStub);

                // 验证配置函数被调用4次（SSH协议）
                expect(updateConfigFnStub.callCount).to.equal(4);
                
                // 验证SSH内网域名重定向配置
                expect(updateConfigFnStub.firstCall.args[2]).to.include('url.git@internal.codeup.aliyun.com:.insteadOf');
                expect(updateConfigFnStub.firstCall.args[3]).to.include('git@codeup.aliyun.com/');
                
                expect(updateConfigFnStub.secondCall.args[2]).to.include('url.git@internal.codeup.aliyun.com:.insteadOf');
                expect(updateConfigFnStub.secondCall.args[3]).to.include('git@codeup.aliyun.com:');
            });

            it('should not set inner host config when gitHost is not codeup.aliyun.com', async () => {
                getHostStub.returns('github.com');
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN = 'internal.github.com';
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP = '192.168.1.1';
                
                const input = {
                    gitRepo: 'github.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('add', input, true, updateConfigFnStub);

                // 验证内网域名没有被设置
                expect(stepInfoStub.calledWith(sinon.match(/gitInnerHost = internal\.github\.com/))).to.be.false;
                
                // 验证配置函数仍然被调用（但使用外网域名，由于gitHost==gitInnerHost，只调用4次）
                expect(updateConfigFnStub.callCount).to.equal(4);
            });

            it('should not set inner host config when environment variables are missing', async () => {
                getHostStub.returns('codeup.aliyun.com');
                // 不设置环境变量
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('add', input, true, updateConfigFnStub);

                // 验证内网域名没有被设置
                expect(stepInfoStub.calledWith(sinon.match(/gitInnerHost =/))).to.be.false;
                
                // 验证配置函数仍然被调用（但使用外网域名，由于gitHost==gitInnerHost，只调用4次）
                expect(updateConfigFnStub.callCount).to.equal(4);
            });
        });

        describe('组合2: action="add" + useInnerApiHost=false', () => {
            it('should set outer host config when useInnerApiHost is false', async () => {
                getHostStub.returns('codeup.aliyun.com');
                // 不设置环境变量，确保 gitInnerHost == gitHost
                delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN;
                delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP;
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('add', input, false, updateConfigFnStub);

                // 验证内网域名没有被设置
                expect(stepInfoStub.calledWith(sinon.match(/gitInnerHost = internal\.codeup\.aliyun\.com/))).to.be.false;
                
                // 验证配置函数被调用（使用外网域名，由于gitHost==gitInnerHost，只调用4次）
                expect(updateConfigFnStub.callCount).to.equal(4);
                
                // 验证外网域名配置（没有重定向）
                // 第一个调用是 git@codeup.aliyun.com/ 的配置
                expect(updateConfigFnStub.firstCall.args[2]).to.include('codeup.aliyun.com/.insteadOf');
                expect(updateConfigFnStub.firstCall.args[3]).to.include('git@codeup.aliyun.com/');
            });
        });

        describe('组合3: action="unset" + useInnerApiHost=true', () => {
            it('should unset inner host config when action is unset', async () => {
                getHostStub.returns('codeup.aliyun.com');
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN = 'internal.codeup.aliyun.com';
                process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP = '192.168.1.1';
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('unset', input, true, updateConfigFnStub);

                // 验证配置函数被调用（清除配置，使用内网域名，调用6次）
                expect(updateConfigFnStub.callCount).to.equal(6);
                
                // 验证action参数是'unset'
                expect(updateConfigFnStub.firstCall.args[0]).to.equal('unset');
            });
        });

        describe('组合4: action="unset" + useInnerApiHost=false', () => {
            it('should unset outer host config when action is unset and useInnerApiHost is false', async () => {
                getHostStub.returns('codeup.aliyun.com');
                // 不设置环境变量，确保 gitInnerHost == gitHost
                delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_DOMAIN;
                delete process.env.FLOW_FEATURE_CODEUP_INTERNAL_IP;
                
                const input = {
                    gitRepo: 'codeup.aliyun.com/repo',
                    workDir: '/path/to/repo',
                    httpUrlWithCredential: true,
                    user: 'user',
                    password: 'password',
                    httpPolicy: 'https'
                } as IGitSourceParams;

                await updateGitConfigSettings('unset', input, false, updateConfigFnStub);

                // 验证配置函数被调用（清除配置，由于不设置环境变量，gitInnerHost==gitHost，调用4次）
                expect(updateConfigFnStub.callCount).to.equal(4);
                
                // 验证action参数是'unset'
                expect(updateConfigFnStub.firstCall.args[0]).to.equal('unset');
            });
        });
    });

    describe('URL类型测试', () => {
        it('should handle SSH URLs correctly', async () => {
            getHostStub.returns('github.com');
            const input = {
                gitRepo: 'github.com/repo',
                workDir: '/path/to/repo',
                sshUrl: true
            } as IGitSourceParams;

            await updateGitConfigSettings('add', input, false, updateConfigFnStub);

            expect(updateConfigFnStub.callCount).to.equal(2);
            
            // 验证SSH配置
            expect(updateConfigFnStub.firstCall.args[2]).to.include('url.git@github.com:.insteadOf');
            expect(updateConfigFnStub.firstCall.args[3]).to.include('http://github.com/');
        });

        it('should handle URLs without credentials or SSH', async () => {
            getHostStub.returns('github.com');
            const input = {
                gitRepo: 'github.com/repo',
                workDir: '/path/to/repo'
                // 既没有 httpUrlWithCredential 也没有 sshUrl
            } as IGitSourceParams;

            await updateGitConfigSettings('add', input, false, updateConfigFnStub);

            // 应该没有配置更新
            expect(updateConfigFnStub.callCount).to.equal(0);
        });
    });

    describe('边界情况测试', () => {
        it('should handle empty gitRepo gracefully', async () => {
            getHostStub.returns('github.com');
            const input = {
                gitRepo: '',
                workDir: '/path/to/repo',
                httpUrlWithCredential: true,
                user: 'user',
                password: 'password',
                httpPolicy: 'https'
            } as IGitSourceParams;

            await updateGitConfigSettings('add', input, false, updateConfigFnStub);

            // 应该正常处理
            expect(updateConfigFnStub.callCount).to.equal(4);
        });
    });
});
